<template>
  <el-container class="slot-container">
    <el-main>
      <div ref="domlistRef">
        <div class="dom-list">
          <h1 class="my-title" id="slot1">简单的插槽内容</h1>
          <el-divider content-position="left">案例区域(组件页面上的效果)</el-divider>
          <div>
            <slot1>简单的插槽</slot1>
          </div>
          <el-divider>代码分析区域</el-divider>

          <el-divider content-position="left">组件使用(调用组件)</el-divider>
          <code-beautify :htmlCode="code1"></code-beautify>
          <el-divider content-position="left"> slot1 组件中的代码</el-divider>
          <code-beautify :htmlCode="code2"></code-beautify>
          <el-divider content-position="left">在浏览器中渲染的就是下面的样子</el-divider>
          <code-beautify :htmlCode="code3"></code-beautify>
          <p class="note-text">注：当组件渲染的时候，相当于&lt;slot>&lt;/slot> 将会被替换为文字“简单的插槽”。</p>
        </div>

        <div class="dom-list">
          <h1 class="my-title" id="slot2">插槽内容包括 HTML</h1>
          <el-divider content-position="left">案例区域(组件最后的效果)</el-divider>
          <div>
            <slot1>
              <i class="el-icon-edit">我是icon图标+文字</i>
            </slot1>
          </div>
          <p class="note-text">注：插槽还可以包含任何模板代码，包括 HTML或其他组件。</p>
          <el-divider>代码分析区域</el-divider>

          <el-divider content-position="left">组件使用</el-divider>
          <code-beautify :htmlCode="code4"></code-beautify>
          <el-divider content-position="left">在 slot1 的模板中</el-divider>
          <code-beautify :htmlCode="code5"></code-beautify>
          <el-divider content-position="left">在浏览器中渲染的就是下面的样子</el-divider>
          <code-beautify :htmlCode="code6"></code-beautify>
          <p class="note-text">注：当组件渲染的时候，相当于&lt;slot>&lt;/slot> 将会被替换为html“&lt;i class="el-icon-edit">我是icon图标+文字&lt;/i>”。</p>
          <p class="note-text">注：如果 &lt;slot1> 的 template 中没有包含一个 &lt;slot> 元素，则该组件起始标签和结束标签之间的任何内容都会被抛弃。</p>
        </div>

        <div class="dom-list">
          <h1 class="my-title" id="slot3">插槽-备用内容</h1>
          <el-divider content-position="left">案例区域(组件最后的效果)</el-divider>
          <div>
            <span>我是默认的：<slot2></slot2></span>
            <span style="padding-left: 20px;">我是自定义的：<slot2>我的名字我做主</slot2></span>
          </div>
          <el-divider>代码分析区域</el-divider>

          <el-divider content-position="left">组件使用</el-divider>

          <div style="display: flex;margin-bottom: 20px;">
            <div style="flex: 1;">
              <p style="margin: 5px 0;">1、默认的：</p>
              <code-beautify :htmlCode="codeBackUp.code1"></code-beautify>
            </div>
            <div style="flex: 1;margin-left: 20px;">
              <p style="margin: 5px 0;">1、自定义的：</p>
              <code-beautify :htmlCode="codeBackUp.code2"></code-beautify>
            </div>
          </div>

          <el-divider content-position="left">在 slot2 的模板中</el-divider>
          <code-beautify :htmlCode="codeBackUp.code3"></code-beautify>

          <el-divider content-position="left">在浏览器中渲染的就是下面的样子</el-divider>
          <div style="display: flex;margin-bottom: 20px;">
            <div style="flex: 1;">
              <p style="margin: 5px 0;">1、默认的：</p>
              <code-beautify :htmlCode="codeBackUp.code4"></code-beautify>
            </div>
            <div style="flex: 1;margin-left: 20px;">
              <p style="margin: 5px 0;">1、自定义的：</p>
              <code-beautify :htmlCode="codeBackUp.code5"></code-beautify>
            </div>
          </div>
          <p class="note-text">注：当我们在一个父级组件中使用 &lt;slot2> 并且不提供任何插槽内容时：备用内容“我是默认的”将会被渲染。但是如果我们提供内容：则这个提供的内容将会被渲染从而取代备用内容</p>
        </div>

        <div class="dom-list">
          <h1 class="my-title" id="slot4">具名插槽</h1>
          <p class="text-desc">有时我们需要多个插槽。例如对于一个带有如下模板的 &lt;base-layout> 组件：我们希望是如下的布局内容</p>
          <code-beautify :htmlCode="namedSlot.code1"></code-beautify>

          <el-divider content-position="left">案例区域(组件最后的效果)</el-divider>
          <div>
            <baseLayout>
              <template v-slot:header>
                <h1>这里可能有一个页面标题</h1>
              </template>

              <template v-slot:default>
                <p>主要内容的段落。</p>
                <p>And another one.还有一些其他内容</p>
              </template>

              <template v-slot:footer>
                <p>这是一些底部的联系方式等</p>
              </template>
            </baseLayout>
          </div>
          <el-divider>代码分析区域</el-divider>

          <el-divider content-position="left">组件使用</el-divider>
          <p class="note-text">
            注：也就是说，在使用这个组件的时候&lt;template v-slot:header>&lt;h1>这里可能有一个页面标题&lt;/h1>&lt;/template>这一段内容就是替换了base-layout组件中的&lt;slot name="header">&lt;/slot>
          </p>
          <code-beautify :htmlCode="namedSlot.code2"></code-beautify>
          <h2>具名插槽的缩写</h2>
          <code-beautify :htmlCode="namedSlot.code5"></code-beautify>
          <p class="note-text">注意，v-slot 只能添加在 &lt;template> 上</p>
          <el-divider content-position="left">在 base-layout 的模板中</el-divider>
          <code-beautify :htmlCode="namedSlot.code3"></code-beautify>
          <el-divider content-position="left">在浏览器中渲染的就是下面的样子</el-divider>
          <code-beautify :htmlCode="namedSlot.code4"></code-beautify>
        </div>

        <div class="dom-list">
          <h1 class="my-title" id="slot5">作用域插槽</h1>
          <p class="text-desc">有时让插槽内容能够访问子组件中才有的数据是很有用的。当一个组件被用来渲染一个项目数组时，这是一个常见的情况，我们希望能够自定义每个项目的渲染方式。</p>

          <el-divider content-position="left">案例区域(组件最后的效果)</el-divider>
          <div>
            <scopedSlot>
              <template v-slot:default="props">
                <i class="el-icon-star-on"></i>
                <span>{{props.index}}:{{props.item}}</span>
              </template>
            </scopedSlot>
          </div>
          <el-divider>代码分析区域</el-divider>

          <el-divider content-position="left">组件使用</el-divider>
          <code-beautify :htmlCode="scopedSlot.code1"></code-beautify>
          <el-divider content-position="left">独占默认插槽的缩写语法使用</el-divider>
          <code-beautify :htmlCode="scopedSlot.code5"></code-beautify>
          <p class="note-text">注：其实就是可以不写default</p>
          <p class="note-text">注：注意默认插槽的缩写语法不能和具名插槽混用，因为它会导致作用域不明确：(就是说有好几个具名插槽的时候不能这样写)</p>
          <p class="note-text">注：只要出现多个插槽，请始终为所有的插槽使用完整的基于 &lt;template> 的语法：</p>

          <el-divider content-position="left">在 scoped-slot 的模板中</el-divider>
          <code-beautify :htmlCode="scopedSlot.code2" isTitle></code-beautify>
          <code-beautify :jsCode="scopedSlot.code4" isTitle></code-beautify>
          <el-divider content-position="left">在浏览器中渲染的就是下面的样子</el-divider>
          <code-beautify :htmlCode="scopedSlot.code3"></code-beautify>
        </div>

        <div class="dom-list">
          <h1 class="my-title" id="slot6">解构插槽 Prop</h1>

          <el-divider content-position="left">案例区域(组件最后的效果)</el-divider>
          <div>
            <scopedSlot>
              <template v-slot="{item:todo, ndex='未知'}">
                <i class="el-icon-star-on"></i>
                <span>{{ndex}}:{{todo}}</span>
              </template>
            </scopedSlot>
          </div>
          <el-divider>代码分析区域</el-divider>

          <el-divider content-position="left">组件使用</el-divider>
          <p class="note-text">注：效果和作用域插槽是一样的，就是写法不一样：看下面的第2行</p>
          <code-beautify :htmlCode="destSlot.code1"></code-beautify>
          <p class="note-text">注：也可以使用别名,如下所示，效果是一样的</p>
          <code-beautify :htmlCode="destSlot.code2"></code-beautify>
          <p class="note-text">注：你甚至可以定义备用内容，用于插槽 prop 是 undefined 的情形：</p>
          <code-beautify :htmlCode="destSlot.code3"></code-beautify>
          <h2 class="my-sub-title">动态插槽名</h2>
          <p class="note-text">注：动态指令参数也可以用在 v-slot 上，来定义动态的插槽名</p>
          <code-beautify :htmlCode="destSlot.code4"></code-beautify>
        </div>


      </div>
    </el-main>
    <el-aside width="200px">
      <ul id="nav-list">
        <li :class="{'active': active === index}" v-for="(item, index) in list" @click="navClick(item, index)">
          {{item.name}}
        </li>
      </ul>
    </el-aside>
  </el-container>
</template>

<script>
  import {ref, watch, computed, nextTick, onMounted} from 'vue'
  import {css_beautify, html_beautify} from "js-beautify"
  import slot1 from "./slot1.vue"
  import slot2 from "./slot2.vue"
  import baseLayout from "./base-layout.vue"
  import scopedSlot from "./scoped-slot.vue"

  export default {
    name: "slot",
    components: {
      slot1,
      slot2,
      baseLayout,
      scopedSlot
    },
    props: ['scrollTop'],
    emits: ['updateVal'],
    setup(props, {emit}) {
      const list = ref([])
      const active = ref(0)
      const listRef = ref(null)
      const domlistRef = ref(null)
      const code1 = ref(null)
      const code2 = ref(null)
      const code3 = ref(null)
      const code4 = ref(null)
      const code5 = ref(null)
      const code6 = ref(null)

      const codeBackUp = ref({})
      const namedSlot = ref({})
      const scopedSlot = ref({})
      const destSlot = ref({})

      let flag = computed(() => props.scrollTop.flag)
      let arr = []
      let domList = null

      list.value = [
        {id: 1, name: '简单的插槽内容', dataId: 'slot1'},
        {id: 2, name: '插槽内容包括 HTML', dataId: 'slot2'},
        {id: 3, name: '插槽-备用内容', dataId: 'slot3'},
        {id: 4, name: '具名插槽', dataId: 'slot4'},
        {id: 5, name: '作用域插槽', dataId: 'slot5'},
        {id: 6, name: '解构插槽 Prop', dataId: 'slot6'},
      ]

      watch(() => props.scrollTop, (newVal)=> {
        if (flag.value && newVal.flag) {
          let newY = newVal.top
          for (let i=0;i<arr.length;i++) {
            const heightTop = arr[i].height
            const heightBottom = arr[i + 1] ? arr[i + 1].height : 0
            console.log(heightTop, heightBottom)
            if (newY<heightTop) {
              active.value = 0
              break
            }
            if (newY >= heightTop && newY <= heightBottom) {
              active.value = i +1
              break
            }
          }
        }
      })

      function navClick(item, index) {
        emit('updateVal', false)
        const dom = document.querySelector('#'+item.dataId)
        const mainDom = document.querySelector('#my-main')
        mainDom.scrollTo({top : dom.offsetTop - 50, behavior : 'smooth'})
        active.value = index
      }

      onMounted(async () => {
        code1.value = html_beautify('<slot1>简单的插槽</slot1>', {indent_size: 2, space_in_empty_paren: true})
        code2.value = html_beautify('<button><slot></slot></button>', {indent_size: 2, space_in_empty_paren: true})
        code3.value = html_beautify('<button>简单的插槽</button>', {indent_size: 2, space_in_empty_paren: true})

        code4.value = html_beautify('<slot1><i class="el-icon-edit">我是icon图标+文字</i></slot1>', {indent_size: 2, space_in_empty_paren: true})
        code5.value = html_beautify('<button><slot></slot></button>', {indent_size: 2, space_in_empty_paren: true})
        code6.value = html_beautify('<button><i class="el-icon-edit">我是icon图标+文字</i></button>', {indent_size: 2, space_in_empty_paren: true})

        codeBackUp.value.code1 = html_beautify('<slot2></slot2>', {indent_size: 2, space_in_empty_paren: true})
        codeBackUp.value.code2 = html_beautify('<slot2>我的名字我做主</slot2>', {indent_size: 2, space_in_empty_paren: true})
        codeBackUp.value.code3 = html_beautify('<button><slot>我是默认的</slot></button>', {indent_size: 2, space_in_empty_paren: true})
        codeBackUp.value.code4 = html_beautify('<button>我是默认的</button>>', {indent_size: 2, space_in_empty_paren: true})
        codeBackUp.value.code5 = html_beautify('<button>我的名字我做主</button>', {indent_size: 2, space_in_empty_paren: true})

        namedSlot.value.code1 = html_beautify('<div class="container"><header><!-- 我们希望把页头放这里 --></header><main><!-- 我们希望把主要内容放这里 --></main><footer><!-- 我们希望把页脚放这里 --></footer></div>', {indent_size: 2, space_in_empty_paren: true})
        namedSlot.value.code2 = html_beautify('<baseLayout>\n<template v-slot:header><h1>这里可能有一个页面标题</h1></template>\n<template v-slot:default><p>主要内容的段落。</p><p>And another one.还有一些其他内容</p></template>\n<template v-slot:footer><p>这是一些底部的联系方式等</p></template>\n</baseLayout>', {indent_size: 2, space_in_empty_paren: true})
        namedSlot.value.code3 = html_beautify('<template><div class="container"><header>\n我是header：<slot name="header"></slot></header><main>\n我是main：<slot></slot></main><footer>\n我是footer：<slot name="footer"></slot></footer></div></template>', {indent_size: 2, space_in_empty_paren: true})
        namedSlot.value.code4 = html_beautify('<div><div class="container"><header>\n我是header： \n<h1 >这里可能有一个页面标题</h1></header><main>\n我是main： \n<p>主要内容的段落。</p><p>And another one.还有一些其他内容</p></main><footer> \n我是footer： \n<p>这是一些底部的联系方式等</p></footer></div></div>', {indent_size: 2, space_in_empty_paren: true})
        namedSlot.value.code5 = html_beautify('<baseLayout>\n<template #header><h1>这里可能有一个页面标题</h1></template>\n<template #default><p>主要内容的段落。</p><p>And another one.还有一些其他内容</p></template>\n<template #footer><p>这是一些底部的联系方式等</p></template>\n</baseLayout>', {indent_size: 2, space_in_empty_paren: true})

        scopedSlot.value.code1 = html_beautify('<scopedSlot>\n<template v-slot:default="props">\n<i class="el-icon-star-on"></i>\n<span>{{props.index}}:{{props.item}}</span>\n</template>\n</scopedSlot>', {indent_size: 2, space_in_empty_paren: true})
        scopedSlot.value.code2 = html_beautify('<ul><li v-for="(item,index) in list"><slot :item="item" :index="index"></slot></li></ul>', {indent_size: 2, space_in_empty_paren: true})
        scopedSlot.value.code3 = html_beautify('<ul><li><i class="el-icon-star-on"></i><span>0:面包</span></li><li><i class="el-icon-star-on"></i><span>1:牛奶</span></li><li><i class="el-icon-star-on"></i><span>2:巧克力</span></li></ul>', {indent_size: 2, space_in_empty_paren: true})
        scopedSlot.value.code4 = css_beautify('data() {return {list: [\'面包\',\'牛奶\',\'巧克力\']}}', {indent_size: 2, space_in_empty_paren: true})
        scopedSlot.value.code5 = html_beautify('<scopedSlot>\n<template v-slot="props">\n<i class="el-icon-star-on"></i>\n<span>{{props.index}}:{{props.item}}</span>\n</template>\n</scopedSlot>', {indent_size: 2, space_in_empty_paren: true})

        destSlot.value.code1 = html_beautify('<scopedSlot>\n<template v-slot="{item, index}">\n<i class="el-icon-star-on"></i>\n<span>{{index}}:{{item}}</span>\n</template>\n</scopedSlot>', {indent_size: 2, space_in_empty_paren: true})
        destSlot.value.code2 = html_beautify('<scopedSlot>\n<template v-slot="{item:todo, index=\'未知\'}">\n<i class="el-icon-star-on"></i>\n<span>{{i}}:{{todo}}</span>\n</template>\n</scopedSlot>', {indent_size: 2, space_in_empty_paren: true})
        destSlot.value.code3 = html_beautify('<scopedSlot>\n<template  v-slot="{ item = \'Placeholder\' }">\n<i class="el-icon-star-on"></i>\n<span>{{item}}</span>\n</template>\n</scopedSlot>', {indent_size: 2, space_in_empty_paren: true})
        destSlot.value.code4 = html_beautify('<scopedSlot>\n<template  v-slot:[dynamicSlotName]>\n<span>代码区......</span>\n</template>\n</scopedSlot>', {indent_size: 2, space_in_empty_paren: true})

        await nextTick()
        // domList = document.querySelectorAll('.dom-list')
        domList = domlistRef.value.children

        let height = 0
        for (let i = 0, len = domList.length; i < len; i++) {
          const item = domList[i]
          let obj = {}
          height += item.clientHeight
          obj.height = height
          obj.index = i
          arr.push(obj)
        }
        console.log('arr:', arr)
      })

      return {
        list,
        active,
        listRef,
        domlistRef,
        code1,
        code2,
        code3,
        code4,
        code5,
        code6,
        codeBackUp,
        namedSlot,
        scopedSlot,
        destSlot,
        navClick
      }
    }
  }
</script>

<style scoped lang="scss">
  .slot-container {
    .el-aside {
      #nav-list {
        position: fixed;
        top: 80px;
        right: 30px;
        li {
          padding: 5px 10px;
          cursor: pointer;
          &.active{
            background: #7e8c8d;
            color: #fff;
          }
          &:hover {
            background: #9daeaf;
          }
        }
      }
    }
  }
</style>
